package com.fdb.efp.console.api.rest;

import com.fdb.basic.framework.core.constant.ApplicationConstance;
import com.fdb.basic.framework.core.constant.BaseConstant;
import com.fdb.basic.framework.core.constant.ResponseData;
import com.fdb.basic.framework.core.util.CookiesUtil;
import com.fdb.basic.framework.core.util.RSAUtils;
import com.fdb.basic.framework.core.util.StringUtil;
import com.fdb.basic.framework.core.vo.UserInfo;
import com.fdb.basic.framework.web.controller.AbstractController;
import com.fdb.efp.console.service.facade.SUserService;
import com.fdb.efp.console.service.vo.SUserVO;
import com.fdb.efp.console.api.util.ValidateCode;
import com.fdb.efp.console.common.constant.E4AConstant;
import com.fdb.efp.console.common.constant.ValidateCheck;
import com.fdb.efp.console.service.facade.E4AService;
import com.fdb.efp.console.service.vo.AuthInfoVO;
import com.fdb.efp.console.service.vo.SMenuUserVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.Cookie;
import java.util.Objects;

/**
 * E4A控制器
 * @author fuzm
 *
 */
@RestController
@RequestMapping("/api")
public class E4AController extends AbstractController {
	
	private static Logger logger = LoggerFactory.getLogger(E4AController.class);
	@Autowired
	private E4AService e4aService;

	@Autowired
	@Qualifier("sUserService")
	private SUserService sUserService;
	
	@RequestMapping(value="/oauth/token", method=RequestMethod.POST)
	public  @ResponseBody ResponseData<String> authToken(@RequestBody AuthInfoVO authInfoVO) {
		
		String clientId = authInfoVO.getClientId();
		String imageCode = authInfoVO.getImageCode();
		boolean check = e4aService.verifyCodeImage(clientId, imageCode);

		//验证完，先刷新验证码
	    ValidateCode vCode = new ValidateCode(120, 40, 4, 100);
	    //缓存到redis中
	    e4aService.cacheValidateCode(clientId, vCode.getCode());
		
		if(check) {
			authInfoVO.setSessionId(this.httpRequest.getSession().getId());
			
//			String rsaPassword = authInfoVO.getPassword();
//			//RSA解密
//			try {
//				String password = RSAUtility.decryptByBase64(rsaPassword, E4AConstant.RSA_PRIVATE_KEY);
//				authInfoVO.setPassword(password);
//			} catch(Exception e) {
//				logger.error("RSA解密失败" + e.getMessage(), e);
//				ResponseData<String> data = this.getResponseData(null);
//				data.setMessage("登录失败（密码解密失败），请重试或联系系统管理员！");
//				return data;
//			}
			
			AuthInfoVO authInfo = e4aService.authToken(authInfoVO);
			//登录成功
			if (authInfo != null && StringUtil.isNotEmpty(authInfo.getToken())) {
				//将后续校验用到的信息存入cookies
				CookiesUtil.addCookie(this.httpResponse, E4AConstant.COOKIES_KEY_SSO_CLIENT, authInfo.getSessionId(), -1);
				CookiesUtil.addCookie(this.httpResponse, E4AConstant.COOKIES_KEY_SSO_TIMESTAMP, String.valueOf(authInfo.getTimestamp()), -1);
				CookiesUtil.addCookie(this.httpResponse, E4AConstant.COOKIES_KEY_SSO_MD5, authInfo.getMd5(), -1);
				/** 【2019D0509】【(问题编号)】 @date 2019/12/11 */
				if(BaseConstant.NO_N.equals(getUserIsInitPwd(authInfoVO.getUsercode()))){
					return ResponseData.create(authInfo.getToken(), ApplicationConstance.SUCCESS, "IS_INIT_PWD_N", true);
				}else {
					return this.getResponseData(authInfo.getToken());
				}
			} else { //登录失败
				ResponseData<String> data = this.getResponseData(null);
				data.setMessage("登录失败，用户名或密码不正确或用户已被注销");
				return data;
			}
		} else {
			ResponseData<String> data = this.getResponseData(null);
			data.setCode("900000");
			data.setMessage("图形校验码验证失败");
			return data;
		}
	}
	
	/**
	 * 获取session登录信息
	 * @param token
	 * @return
	 */
	@RequestMapping(value="/session/info", method=RequestMethod.POST)
	public @ResponseBody ResponseData<UserInfo> getSessionInfo() {
		ResponseData<UserInfo> data = null;
		try {
			UserInfo userInfo = this.getUserInfo();
			//为减少前端信息存储，过滤掉前端不用的信息
			userInfo.setMenuCtrls(null);
			data = this.getResponseData(userInfo);
		} catch(Exception e) {
			logger.error("获取session登录信息失败" + e.getMessage(), e);
			//将响应码改成验证失败
			this.httpResponse.setStatus(401);
		}
		return data;
	}
	
	/**
	 * 登出
	 * @param loginInfoVO
	 * @return
	 */
	@RequestMapping(value="/logout", method=RequestMethod.POST)
	public @ResponseBody ResponseData<Boolean> logout() {
		ResponseData<Boolean> data = null;
		try {
			AuthInfoVO vo = new AuthInfoVO();
			vo.setSessionId(CookiesUtil.getCookieValue(this.httpRequest, E4AConstant.COOKIES_KEY_SSO_CLIENT));
			vo.setTimestamp(Long.valueOf(CookiesUtil.getCookieValue(this.httpRequest, E4AConstant.COOKIES_KEY_SSO_TIMESTAMP)));
			vo.setMd5(CookiesUtil.getCookieValue(this.httpRequest, E4AConstant.COOKIES_KEY_SSO_MD5));
			this.httpRequest.getSession().removeAttribute(UserInfo.SEESION_USER_KEY);
			this.httpRequest.getSession().invalidate();
			//清除Cookie 信息
			Cookie[] cookies = this.httpRequest.getCookies();
			for (Cookie c : cookies) {
				if ( E4AConstant.COOKIES_KEY_SSO_CLIENT.equals(c.getName()) 
					|| E4AConstant.COOKIES_KEY_SSO_TIMESTAMP.equals(c.getName())
					|| E4AConstant.COOKIES_KEY_SSO_MD5.equals(c.getName()) ) {
					c.setMaxAge(0);
					this.httpResponse.addCookie(c);
				}
			}
			logger.info("清空session");
			data = this.getResponseData(e4aService.logout(vo));
		} catch(Exception e) {
			//this.httpResponse.setStatus(401);
			logger.error("登出失败" + e.getMessage(), e);
		}
		return data;
	}
	
	/**
	 * 密码修改
	 * @return
	 */
	@RequestMapping(value="/account/modifyUserPwd", method=RequestMethod.POST)
	public @ResponseBody ResponseData<Boolean> changePasswrod(@RequestBody AuthInfoVO authInfoVO) {
		ResponseData<Boolean> data = null;
		
		String newPassword = authInfoVO.getNewPassword();
		String decodeNewPassword = "";
		try {
			decodeNewPassword = new String(RSAUtils.decryptByPrivateKey(newPassword, E4AConstant.RSA_PRIVATE_KEY), "UTF-8");
		} catch (Exception e) {
			logger.error("RSA解密失败" + e.getMessage(), e);
			data = this.getResponseData(false);
			data.setMessage("密码修改失败（密码解密失败），请重试或联系管理员！");
			return data;
		}
		
		//判断新密码是否符合规则
		if(!ValidateCheck.validatePasswordRule(decodeNewPassword)) {
			data = this.getResponseData(false);
			data.setMessage("密码必须包含数字、字母或特殊字符(~!@#$%^&*)的至少两种");
		} else {
			AuthInfoVO resultInfo = e4aService.modifyUserPassword(authInfoVO);
			if(resultInfo != null) {
				if(resultInfo.isChangeSuccess()) {
					data = this.getResponseData(true);
				} else {
					data = this.getResponseData(false);
					data.setMessage(resultInfo.getMessage());
				}
			} else {
				data = this.getResponseData(false);
			}
		}
		
		return data;
	}
	
	/**
	 * 加载用户菜单及控制点权限
	 * @param token
	 * @return
	 */
	@RequestMapping(value="/account/menuandcontr", method=RequestMethod.POST)
	public @ResponseBody ResponseData<SMenuUserVO> menuAndContr() {
		ResponseData<SMenuUserVO> data = null;
		try {
			UserInfo userInfo = this.getUserInfo();
			SMenuUserVO vo = null;
			//验证成功
			if (userInfo != null) {
				vo = e4aService.queryUserMenuInfo(userInfo.getUserId());
			}
			data = this.getResponseData(vo);
		} catch(Exception e) {
			logger.error("加载用户菜单及控制点权限失败" + e.getMessage(), e);
		}
		return data;
	}
	
	/**
	 * 获取图形校验码
	 * @return
	 */
	@RequestMapping(value="/codeImage", method=RequestMethod.GET)
	public @ResponseBody ResponseData<String> createCodeImage(@RequestParam("clientId") String clientId) {
		try {
			if(StringUtil.isNotEmpty(clientId)) {
				// 设置响应的类型格式为图片格式  
			    this.httpResponse.setContentType("image/jpeg");  
			    //禁止图像缓存
			    httpResponse.setHeader("Pragma", "no-cache");  
			    httpResponse.setHeader("Cache-Control", "no-cache");  
			    httpResponse.setDateHeader("Expires", 0);  

			    //生成图形验证码
			    ValidateCode vCode = new ValidateCode(120, 40, 4, 100);  
			    vCode.write(httpResponse.getOutputStream());
			    
			    //缓存到redis中
			    e4aService.cacheValidateCode(clientId, vCode.getCode());
			} else {
				logger.error("verify code image error for: clientId is null");
			}
			
		} catch (Exception e) {
			logger.error("获取图形校验码失败" + e.getMessage(), e);
		}
		
	    return null;
	}
	
	/**
	 * 校验图形码
	 * @return
	 */
	@RequestMapping(value="/codeImage/verifyCodeImage", method=RequestMethod.POST)
	public @ResponseBody ResponseData<Boolean> verifyCodeImage(@RequestBody AuthInfoVO authInfoVO) {
		boolean check = false;
		try {
			String clientId = authInfoVO.getClientId();
			String imageCode = authInfoVO.getImageCode();
			
			check = e4aService.verifyCodeImage(clientId, imageCode);
		} catch (Exception e) {
			logger.error("校验图形码失败" + e.getMessage(), e);
		}
	    return this.getResponseData(check);
	}

	private String getUserIsInitPwd(String userCode){
		SUserVO sUserVO = new SUserVO();
		sUserVO.setUserCode(userCode);
		sUserVO = sUserService.queryByPk(sUserVO);
		if(Objects.isNull(sUserVO)){
			logger.error("通过用户编号:" + userCode + "获取到的用户信息为空！");
			return null;
		}
		logger.info("用户:" + userCode + "是否已修改初始密码标识为:" + sUserVO.getIsInitPwd());
		return sUserVO.getIsInitPwd();
	}

}
